package org.tamal.classinfo;

import java.io.DataInputStream;
import java.io.IOException;

/**
 * This class represents Field Structure.
 * @author Tamal Kanti Nath
 */
public final class Field {
    private final ClassInfo cls;
    private int accessFlags;
    private int nameIndex;
    private int descriptorIndex;
    private Attribute[] attributes;

    private Field(DataInputStream in, ClassInfo cls) throws IOException {
        this.cls = cls;
        accessFlags = in.readUnsignedShort();
        nameIndex = in.readUnsignedShort();
        descriptorIndex = in.readUnsignedShort();
        attributes = Attribute.readAttributes(in, cls);
    }

    /**
     * Returns raw accessFlags.
     * @return the raw accessFlags
     */
    public int getRawAccessFlags() {
        return accessFlags;
    }

    /**
     * Returns accessFlags.
     * @return the accessFlags
     */
    public String getAccessFlags() {
        return AccessFlag.getFieldFlag(accessFlags);
    }

    /**
     * Returns Method name index.
     * @return the Method name index
     */
    public int getNameIndex() {
        return nameIndex;
    }

    /**
     * Returns Field name.
     * @return the Field name
     */
    public String getName() {
        return cls.getPool()[nameIndex].toString();
    }

    /**
     * Returns Method descriptor index.
     * @return the Method descriptor index
     */
    public int getDescriptorIndex() {
        return descriptorIndex;
    }

    /**
     * Returns Field descriptor.
     * @return the Field descriptor
     */
    public String getDescriptor() {
        return cls.getPool()[descriptorIndex].getStringData().replace('/', '.');
    }

    /**
     * Returns attributes.
     * @return the attributes
     */
    public Attribute[] getAttributes() {
        return attributes;
    }

    @Override
    public String toString() {
        String str = Util.formatNameType(getName(), getDescriptor());
        return Util.insertClass(cls.getThisClass(), str);
    }

    /**
     * Static method to read fields from a class.
     * @param in The input stream for a class
     * @param cls The ClassInfo reference
     * @return An array of ConstantPool
     * @throws IOException if any IO exception occurs
     * @see ClassInfo
     */
    static Field[] readFields(DataInputStream in, ClassInfo cls)
        throws IOException {
        Field[] field = new Field[in.readUnsignedShort()];
        for (int i = 0; i < field.length; ++i) {
            field[i] = new Field(in, cls);
        }
        return field;
    }
}
